package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.CouponInfoMapper;
import cc.rengu.igas.momp.common.dao.McDetailInfoMapper;
import cc.rengu.igas.momp.common.dao.McUserInfoMapper;
import cc.rengu.igas.momp.common.dao.impl.CouponInfoMapperImpl;
import cc.rengu.igas.momp.common.dao.impl.McDetailInfoMapperImpl;
import cc.rengu.igas.momp.common.dao.impl.McUserInfoMapperImpl;
import cc.rengu.igas.momp.common.entity.TMCouponInfo;
import cc.rengu.igas.momp.common.entity.TMMcCouponInfo;
import cc.rengu.igas.momp.common.entity.TMMcUserInfo;
import cc.rengu.igas.momp.common.enums.CouponStatusEnum;
import cc.rengu.igas.momp.common.enums.McStatusEnum;
import cc.rengu.igas.momp.common.enums.RespCodeEnum;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.ClaimCouponMcInfoBean;
import cc.rengu.igas.momp.facade.bean.CouponListInfoBean;
import cc.rengu.igas.momp.facade.request.ClaimCouponRequest;
import cc.rengu.igas.momp.facade.response.ClaimCouponResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.dbs.Database;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 卡券领取功能实现
 *
 * @author Jinan Liu
 * @date 2020/4/2 17:49
 */
public class ClaimCouponService extends RadpService {

    private String globalInstId;
    private String globalTimeStamp;
    private String globalTxnDate;
    private String globalTxnTime;
    private BigDecimal zero = BigDecimal.ZERO;
    /**
     * 手机号
     */
    private String phoneNo;
    /**
     * 银行卡号
     */
    private String cardNo;
    /**
     * 微信Id
     */
    private String wechatId;
    /**
     * 支付宝Id
     */
    private String alipayId;
    /**
     * 用户标志  1：未上送useId 2：单个userId 3：json字符串
     */
    private String userIdFlag;
    /**
     * 核心客户号
     */
    private String coreComId;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            ClaimCouponRequest claimCouponRequest = new ClaimCouponRequest();
            ConvertUtil.convertOutput(claimCouponRequest);

            ClaimCouponResponse claimCouponResponse = new ClaimCouponResponse();
            claimCouponResponse.setHeader(claimCouponRequest.getHeader());
            BizResponse<ClaimCouponResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(claimCouponResponse);

            globalInstId = claimCouponRequest.getHeader().getInstId();
            globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
            globalTxnDate = claimCouponRequest.getHeader().getTransDate();
            globalTxnTime = claimCouponRequest.getHeader().getTransTime();

            // 服务调用
            BizResponse<ClaimCouponResponse> bizResponseNew = claimCoupon(xmlTreeUtil, claimCouponRequest, claimCouponResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 领取卡券流程
     *
     * @param xmlTreeUtil         内部XML树
     * @param claimCouponRequest  领取卡券接口请求对象
     * @param claimCouponResponse 领取卡券接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.ClaimCouponResponse> 领取卡券接口应答对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/5/23 16:59
     */
    private BizResponse<ClaimCouponResponse> claimCoupon(XmlTreeUtil xmlTreeUtil, ClaimCouponRequest claimCouponRequest, ClaimCouponResponse claimCouponResponse) throws Exception {

        BizResponse<ClaimCouponResponse> bizResponse = new BizResponse<>();

        /* 用户领取卡券 */
        List<CouponListInfoBean> couponListInfoBeanList = new ArrayList<>();

        claimCouponList(claimCouponRequest, couponListInfoBeanList);

        claimCouponResponse.setCouponInfoList(couponListInfoBeanList);

        rglog.info("计划领取{}张卡券,成功领取{}张卡券", claimCouponRequest.getMcInfoList().size(), couponListInfoBeanList.size());

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        claimCouponResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        claimCouponResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(claimCouponResponse);

        return bizResponse;
    }

    /**
     * 领取卡券
     *
     * @param claimCouponRequest     领取卡券接口请求对象
     * @param couponListInfoBeanList 卡券列表信息对象
     * @author Jinan Liu
     * @since 2020/4/7 14:23
     */
    private void claimCouponList(ClaimCouponRequest claimCouponRequest, List<CouponListInfoBean> couponListInfoBeanList) throws Exception {

        List<ClaimCouponMcInfoBean> claimCouponMcInfoBeans = claimCouponRequest.getMcInfoList();

        for (ClaimCouponMcInfoBean claimCouponMcInfoBean : claimCouponMcInfoBeans) {
            // 检查上传字段 不能为负数
            checkMcInfoFieldHasNegativeNumber(claimCouponMcInfoBean);

            rglog.info("营销活动编号<{}>，规则编号<{}> 卡券领取开始...", claimCouponMcInfoBean.getMcNo(), claimCouponMcInfoBean.getRuleIndex());
            claimSingleCoupon(claimCouponMcInfoBean, couponListInfoBeanList);
        }

        //如果循环领取完，卡券列表为空，则返回卡券领取失败
        if (couponListInfoBeanList.isEmpty()) {
            rglog.error("卡券领取失败，未领取到任何卡券");
            throw new BizException(RespCodeEnum.FAILED_TO_CLIAM_COUPON_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CLIAM_COUPON_INFO_ERROR.getRespDesc());
        }
    }

    /**
     * 领取单张卡券
     *
     * @param claimCouponMcInfoBean  营销活动信息列表-领取卡券使用
     * @param couponListInfoBeanList 卡券列表信息对象
     * @author Jinan Liu
     * @date 2020/4/7 15:10
     */
    private void claimSingleCoupon(ClaimCouponMcInfoBean claimCouponMcInfoBean, List<CouponListInfoBean> couponListInfoBeanList) throws Exception {

        CouponListInfoBean couponListInfoBean;

        /* 根据锁定标志判断业务流程 */
        switch (claimCouponMcInfoBean.getCouponLockFlag()) {
            case CommonConstant.CLAIM_COUPON_LOCK:
                /* 锁定卡券 */
                couponListInfoBean = lockSingleCoupon(claimCouponMcInfoBean);
                break;
            case CommonConstant.CLAIM_COUPON_UNLOCK_S:
                //购买金额
                String purchaseAmt = claimCouponMcInfoBean.getPurchaseAmt();
                /* 判断类型，如果是购买型的卡券 解锁卡券，并领取卡券 ，免费型的卡券直接领取卡券*/
                if (null == purchaseAmt || CommonConstant.ZERO_COMMON_CONSTANT.equals(purchaseAmt) || "".equals(purchaseAmt)) {
                    rglog.info("用户<{}> 开始领取免费型卡券", claimCouponMcInfoBean.getClaimUser());
                    //领取免费型卡券
                    couponListInfoBean = claimSingleCouponForFree(claimCouponMcInfoBean);
                } else {
                    rglog.info("营销活动编号<{}> 用户<{}> 开始领取购买型卡券", claimCouponMcInfoBean.getCouponNo(), claimCouponMcInfoBean.getClaimUser());
                    //领取购买型卡券
                    couponListInfoBean = unlockSingleCouponForClaiming(claimCouponMcInfoBean);
                }

                break;
            case CommonConstant.CLAIM_COUPON_UNLOCK_F:
                /* 解锁卡券，并解除领取状态 */
                couponListInfoBean = unlockSingleCouponForFailure(claimCouponMcInfoBean);
                break;
            default:
                rglog.error("不支持的锁定标志! LOCK_FLAG=<{}>", claimCouponMcInfoBean.getCouponLockFlag());
                throw new BizException(RespCodeEnum.FAILED_TO_CLIAM_COUPON_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CLIAM_COUPON_INFO_ERROR.getRespDesc());
        }


        if (null != couponListInfoBean) {
            couponListInfoBeanList.add(couponListInfoBean);
        }
    }

    /**
     * 领取卡券时第一次调用锁定一张指定营销活动指定规则下的可用卡券
     *
     * @param claimCouponMcInfoBean 营销活动信息列表-领取卡券使用
     * @return cc.rengu.igas.momp.facade.bean.CouponListInfoBean 卡券列表信息对象
     * @author Jinan Liu
     * @date 2020/6/1 17:42
     */
    private CouponListInfoBean lockSingleCoupon(ClaimCouponMcInfoBean claimCouponMcInfoBean) {

        /* 营销活动信息正式表查询 */
        TMMcCouponInfo mcCouponInfo;
        String mcNo = claimCouponMcInfoBean.getMcNo();
        String ruleIndex = claimCouponMcInfoBean.getRuleIndex();
        String claimUser = claimCouponMcInfoBean.getClaimUser();

        try {
            mcCouponInfo = selectCouponMcInfoByPrimaryKey(globalInstId, mcNo);
            if (null != mcCouponInfo) {
                /* 检查卡券营销活动状态 */
                if (!McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcCouponInfo.getMcStatus()) && !McStatusEnum.TESTING.getMcStatusCode().equals(mcCouponInfo.getMcStatus())) {
                    /* 营销活动不在进行中,不可领取卡券 */
                    rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态不是进行中或测试中，不可领取卡券", mcNo);
                    return null;
                }
                if (McStatusEnum.TESTING.getMcStatusCode().equals(mcCouponInfo.getMcStatus())) {
                    //查询该用户，活动下的营销用户信息表信息
                    List<TMMcUserInfo> userInfoList = checkUserInfo(globalInstId, mcNo, claimUser);
                    if (null == userInfoList) {
                        rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态为测试中，且领取人<{}>不是指定测试用户，不可领取卡券", mcNo, claimUser);
                        return null;
                    } else {
                        List<TMMcUserInfo> testUserList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_TESTING)).collect(Collectors.toList());
                        if (testUserList.size() == 0) {
                            rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态为测试中，且领取人<{}>不是指定测试用户，不可领取卡券", mcNo, claimUser);
                            return null;
                        }
                    }
                }

                /* 检查当前系统日期是否在对应卡券营销活动的有效期内 */
                int returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcCouponInfo.getMcStartDate(), mcCouponInfo.getMcEndDate());
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("领取卡券日期<{}>并未在卡券营销活动<{}>的有效期<{}>~<{}>内,不可领取!", globalTxnDate,
                            mcNo, mcCouponInfo.getMcStartDate(), mcCouponInfo.getMcEndDate());
                    return null;
                }

                /* 查询卡券信息表中剩余可领取卡券信息 */
                TMCouponInfo couponInfo = new TMCouponInfo();
                couponInfo.setInstId(globalInstId);
                couponInfo.setMcNo(mcNo);
                couponInfo.setRuleIndex(ruleIndex);

                /* 查询未生效或未领取的卡券状态的卡券 */
                TMCouponInfo tmCouponInfo = selectClaimableCouponbyRuleIndex(couponInfo);
                if (null == tmCouponInfo) {
                    rglog.error("法人机构<{}>的卡券营销活动<{}>的规则<{}>没有剩余可领取卡券!", globalInstId, mcNo, ruleIndex);
                    return null;
                }

                /* 更新卡券状态 */
                couponInfo.setInstId(globalInstId);
                couponInfo.setCouponNo(tmCouponInfo.getCouponNo());
                couponInfo.setCouponStatus(CouponStatusEnum.LOCKED.getCouponStatusCode());
                couponInfo.setRemark1(tmCouponInfo.getCouponStatus());
                returnCode = updateCouponStatusByPrimaryKey(couponInfo);
                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新卡券状态失败! RETURN_CODE=<{}>", returnCode);
                    return null;
                }

                /* 转换卡券信息 */
                tmCouponInfo.setCouponStatus(CouponStatusEnum.LOCKED.getCouponStatusCode());
                tmCouponInfo.setClaimUserId(claimCouponMcInfoBean.getClaimUser());
                tmCouponInfo.setClaimDate(globalTxnDate);
                tmCouponInfo.setClaimTime(globalTxnTime);
                tmCouponInfo.setClaimType(claimCouponMcInfoBean.getClaimType());
                return convertCouponInfo(tmCouponInfo);

            } else {
                /* 获取卡券营销活动信息失败 */
                rglog.error("机构号 INST_ID=<{}>, 营销活动编号 MC_NO=<{}>，<{}>", globalInstId, mcNo, RespCodeEnum.GET_COUPON_MC_DETAIL_ERROR.getRespDesc());
                return null;
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }

    /**
     * 领取卡券时第二次调用解锁指定卡券并领取卡券
     *
     * @param claimCouponMcInfoBean 营销活动信息列表-领取卡券使用
     * @return cc.rengu.igas.momp.facade.bean.CouponListInfoBean 卡券列表信息对象
     * @author Jinan Liu
     * @date 2020/6/1 17:42
     */
    private CouponListInfoBean unlockSingleCouponForClaiming(ClaimCouponMcInfoBean claimCouponMcInfoBean) {

        /* 营销活动信息正式表查询 */
        TMMcCouponInfo tmMcCouponInfo;
        String mcNo = claimCouponMcInfoBean.getMcNo();
        String couponNo = claimCouponMcInfoBean.getCouponNo();

        try {
            tmMcCouponInfo = selectCouponMcInfoByPrimaryKey(globalInstId, mcNo);
            if (null != tmMcCouponInfo) {

                /* 根据卡券编号查询卡券基本信息 */
                TMCouponInfo couponInfo = new TMCouponInfo();
                couponInfo.setInstId(globalInstId);
                couponInfo.setCouponNo(couponNo);

                /* 查询上送卡券编号的卡券信息 当前卡券应该是锁定状态*/
                TMCouponInfo tmCouponInfo = selectLockedCouponByPrimaryKey(couponInfo);
                if (null == tmCouponInfo) {
                    rglog.error("法人机构<{}>的卡券营销活动<{}>卡券编号<{}>的卡券信息查询失败!", globalInstId, mcNo, couponNo);
                    return null;
                }

                couponInfo.setInstId(globalInstId);
                couponInfo.setCouponNo(couponNo);
                couponInfo.setClaimUserId(claimCouponMcInfoBean.getClaimUser());
                couponInfo.setClaimDate(globalTxnDate);
                couponInfo.setClaimTime(globalTxnTime);
                couponInfo.setClaimType(claimCouponMcInfoBean.getClaimType());
                couponInfo.setUpdateTime(globalTimeStamp);

                /* 根据卡券生效时间更新卡券状态 */
                if (CommonConstant.COUPON_IMMEDIATE_AVAILABLE.equals(tmMcCouponInfo.getAvailableDate())) {
                    /* 卡券实时生效,需要将卡券状态更新为未核销 */
                    couponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
                    tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
                } else {
                    /* 卡券实时生效,需要将卡券状态更新为未生效 */
                    couponInfo.setCouponStatus(CouponStatusEnum.NOT_ENABLED.getCouponStatusCode());
                    tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_ENABLED.getCouponStatusCode());
                }

                /* 根据卡券有效期生成卡券有效期起止日期 */
                int returnCode;
                if (CommonConstant.COUPON_RELATIVE_DATE.equals(tmMcCouponInfo.getCouponDateFlag())) {
                    /* 计算卡券有效起止日期并更新 */
                    calculateCouponAvailableDate(couponInfo, tmMcCouponInfo.getCouponPeriod());
                    tmCouponInfo.setCouponStartDate(couponInfo.getCouponStartDate());
                    tmCouponInfo.setCouponEndDate(couponInfo.getCouponEndDate());

                    /* 更新卡券状态 */
                    returnCode = updateLockedCouponInfoAndDate(couponInfo);

                } else {
                    /* 不需要更新卡券有效期止日期,更新卡券状态 */
                    returnCode = updateLockedCouponInfo(couponInfo);
                }

                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新卡券状态失败! RETURN_CODE=<{}>", returnCode);
                    return null;
                }

                /* 转换卡券信息 */
                tmCouponInfo.setClaimUserId(claimCouponMcInfoBean.getClaimUser());
                tmCouponInfo.setClaimDate(globalTxnDate);
                tmCouponInfo.setClaimTime(globalTxnTime);
                tmCouponInfo.setClaimType(claimCouponMcInfoBean.getClaimType());

                return convertCouponInfo(tmCouponInfo);

            } else {
                /* 获取卡券营销活动信息失败 */
                rglog.error("机构号 INST_ID=<{}>, 营销活动编号 MC_NO=<{}>，<{}>", globalInstId, mcNo, RespCodeEnum.GET_COUPON_MC_DETAIL_ERROR.getRespDesc());
                return null;
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }

    /**
     * 领取卡券时第二次调用解锁指定卡券并退回卡券
     *
     * @param claimCouponMcInfoBean 营销活动信息列表-领取卡券使用
     * @return cc.rengu.igas.momp.facade.bean.CouponListInfoBean 卡券列表信息对象
     * @author Jinan Liu
     * @date 2020/6/1 17:42
     */
    private CouponListInfoBean unlockSingleCouponForFailure(ClaimCouponMcInfoBean claimCouponMcInfoBean) {

        /* 营销活动信息正式表查询 */
        TMMcCouponInfo tmMcCouponInfo;
        String mcNo = claimCouponMcInfoBean.getMcNo();
        String couponNo = claimCouponMcInfoBean.getCouponNo();

        try {
            tmMcCouponInfo = selectCouponMcInfoByPrimaryKey(globalInstId, mcNo);
            if (null != tmMcCouponInfo) {

                /* 根据卡券编号查询卡券基本信息 */
                TMCouponInfo couponInfo = new TMCouponInfo();
                couponInfo.setInstId(globalInstId);
                couponInfo.setCouponNo(couponNo);

                /* 查询未生效或未领取的卡券状态的卡券 */
                TMCouponInfo tmCouponInfo = selectLockedCouponByPrimaryKey(couponInfo);
                if (null == tmCouponInfo) {
                    rglog.error("法人机构<{}>的卡券营销活动<{}>卡券编号<{}>的卡券信息查询失败!", globalInstId, mcNo, couponNo);
                    return null;
                }

                /* 更新卡券状态 */
                couponInfo.setInstId(globalInstId);
                couponInfo.setCouponNo(mcNo);
                couponInfo.setCouponStatus(CouponStatusEnum.NOT_CLAIMED.getCouponStatusCode());
                couponInfo.setRemark1(tmCouponInfo.getCouponStatus());
                couponInfo.setUpdateTime(globalTimeStamp);

                int returnCode = updateCouponStatusByPrimaryKey(couponInfo);
                if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新卡券状态失败! RETURN_CODE=<{}>", returnCode);
                    return null;
                }

                /* 转换卡券信息 */
                tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_CLAIMED.getCouponStatusCode());
                tmCouponInfo.setClaimUserId(claimCouponMcInfoBean.getClaimUser());
                tmCouponInfo.setClaimDate(globalTxnDate);
                tmCouponInfo.setClaimTime(globalTxnTime);
                tmCouponInfo.setClaimType(claimCouponMcInfoBean.getClaimType());
                return convertCouponInfo(tmCouponInfo);

            } else {
                /* 营销活动不在进行中,不可领取卡券 */
                rglog.error("{}}, INST_ID=<{}>, MC_NO=<{}>", RespCodeEnum.GET_COUPON_MC_DETAIL_ERROR.getRespDesc(), globalInstId, mcNo);
                return null;
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }

    /**
     * 领取免费型卡券
     *
     * @param claimCouponMcInfoBean 营销活动信息列表-领取免费型卡券使用
     * @return cc.rengu.igas.momp.facade.bean.CouponListInfoBean 卡券列表信息对象
     * @author liujinan
     * @date 2020/8/11 17:42
     */
    private CouponListInfoBean claimSingleCouponForFree(ClaimCouponMcInfoBean claimCouponMcInfoBean) throws Exception {

        /* 营销活动信息正式表查询 */
        TMMcCouponInfo mcCouponInfo;
        String mcNo = claimCouponMcInfoBean.getMcNo();
        String ruleIndex = claimCouponMcInfoBean.getRuleIndex();
        String claimUser = claimCouponMcInfoBean.getClaimUser();
        String claimUserType = null;
        checkUserId(claimUser);
        //活动配置用户类型
        String mcUserType = null;
        mcCouponInfo = selectCouponMcInfoByPrimaryKey(globalInstId, mcNo);
        if (null != mcCouponInfo) {
            if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                rglog.info("上送userId为Json字符串，需拼接查询营销活动用户表信息");
                claimUser = getUserList();
                rglog.info("claimUser<{}>", claimUser);
            }
            //查询该用户，活动下的营销用户信息表信息
            List<TMMcUserInfo> userInfoList = checkUserInfo(globalInstId, mcNo, claimUser);
            /* 检查卡券营销活动状态 */
            if (!McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcCouponInfo.getMcStatus()) && !McStatusEnum.TESTING.getMcStatusCode().equals(mcCouponInfo.getMcStatus())) {
                /* 营销活动不在进行中,不可领取卡券 */
                rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态不是进行中或测试中，不可领取卡券", mcNo);
                return null;
            }
            if (McStatusEnum.TESTING.getMcStatusCode().equals(mcCouponInfo.getMcStatus())) {
                if (null == userInfoList) {
                    rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态为测试中，且没有测试用户，不可领取卡券", mcNo);
                    return null;
                } else {
                    List<TMMcUserInfo> testUserList = userInfoList.stream().filter(item -> item.getAcctFlag().equals(CommonConstant.ACCT_FLAG_TESTING)).collect(Collectors.toList());
                    if (testUserList.size() == 0) {
                        rglog.error("营销活动编号 MC_NO=<{}> ,营销活动状态为测试中，且领取人<{}>不是指定测试用户，不可领取卡券", mcNo, claimUser);
                        return null;
                    }
                    rglog.info("活动<{}>卡券领取人<{}>", mcNo, testUserList.get(0).getAcctNo());
                    claimUser = testUserList.get(0).getAcctNo();
                    claimUserType = testUserList.get(0).getAcctType();
                }
            } else {
                //活动为进行中
                if (null != userInfoList && !userInfoList.isEmpty()) {
                    mcUserType = userInfoList.get(0).getAcctType();
                }
                if (!StringUtil.isNullorEmpty(mcUserType)) {
                    rglog.info("卡券编号<{}>所属活动<{}>客户范围为指定用户", claimCouponMcInfoBean.getCouponNo(), mcNo);
                    if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {//上送userId为多个
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(mcUserType) || CommonConstant.TWO_COMMON_CONSTANT.equals(mcUserType) || CommonConstant.THREE_COMMON_CONSTANT.equals(mcUserType)) {
                            if (StringUtil.isNullorEmpty(cardNo)) {
                                rglog.info("营销活动编号 MC_NO=<{}> 为指定银行卡号，卡bin，卡产品领取，但未上送银行卡号", mcNo);
                                return null;
                            }
                            rglog.info("卡券领取人<{}>", cardNo);
                            claimUser = cardNo;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_CARD;
                        } else {
                            if (StringUtil.isNullorEmpty(phoneNo)) {
                                rglog.error("营销活动编号 MC_NO=<{}> 为指定手机号领取，但未上送手机号", mcNo);
                                return null;
                            }
                            rglog.info("卡券领取人<{}>", phoneNo);
                            claimUser = phoneNo;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_MOBILE;
                        }
                    } else {
                        rglog.info("上送领取人为单个userId，根据活动配置的客户类型赋值领取人类型");
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(mcUserType) || CommonConstant.TWO_COMMON_CONSTANT.equals(mcUserType) || CommonConstant.THREE_COMMON_CONSTANT.equals(mcUserType)) {
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_CARD;
                        } else {
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_MOBILE;
                        }
                    }
                    if (CommonConstant.TWO_COMMON_CONSTANT.equals(mcUserType)) {
                        rglog.info("营销活动编号 MC_NO=<{}> 为指定卡bin领取,判断是否有日周月季年限制", mcNo);
                        Boolean limitOfJudgingTimes = limitOfJudgingTimes(userInfoList.get(0), claimUser);
                        if (limitOfJudgingTimes) {
                            rglog.info("用户领取卡券次数未超过日周月季年限制");
                        }
                    }
                } else {
                    rglog.info("卡券编号<{}>所属活动<{}>客户范围为所有人，如果卡号，手机号都上送，优先卡号领取卡券", claimCouponMcInfoBean.getCouponNo(), mcNo);
                    claimUserType = claimCouponMcInfoBean.getClaimType();
                    if (userIdFlag.equals(CommonConstant.THREE_COMMON_CONSTANT)) {
                        rglog.info("上送userId为Json字符串");
                        if (!StringUtil.isNullorEmpty(cardNo)) {
                            rglog.info("上送Json字符串有卡号<{}>,优先领取人为卡号", cardNo);
                            claimUser = cardNo;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_CARD;
                        } else if (StringUtil.isNullorEmpty(cardNo) && !StringUtil.isNullorEmpty(phoneNo)) {
                            rglog.info("上送Json字符串无卡号且上送了手机号<{}>,优先领取人为手机号", phoneNo);
                            claimUser = phoneNo;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_MOBILE;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && !StringUtil.isNullorEmpty(wechatId)) {
                            rglog.info("上送Json字符串无卡号和手机号，上送了微信Id<{}>,优先领取人为微信Id", wechatId);
                            claimUser = wechatId;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_WECHAT;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && !StringUtil.isNullorEmpty(alipayId)) {
                            rglog.info("上送Json字符串无卡号和手机号，上送了支付宝Id<{}>,优先领取人为支付宝Id", alipayId);
                            claimUser = alipayId;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_ALIPAY;
                        } else if (StringUtil.isNullorEmpty(cardNo) && StringUtil.isNullorEmpty(phoneNo) && StringUtil.isNullorEmpty(alipayId) &&
                                StringUtil.isNullorEmpty(wechatId) && !StringUtil.isNullorEmpty(coreComId)) {
                            rglog.info("上送Json字符串无卡号无手机号无支付宝id无微信id，上送了核心客户号<{}>,优先领取人为核心客户号", coreComId);
                            claimUser = coreComId;
                            claimUserType = CommonConstant.COUPON_CLAIM_WITH_MEMBER;
                        } else {
                            rglog.error("未上送卡券领取人");
                            return null;
                        }
                    } else {
                        rglog.info("上送领取人为单个userId，且客户范围为所有人，无法判断领取人类型，使用上送的领取人类型");
                    }

                }
            }

            /* 检查卡券营销活动是否是免费型卡券营销活动 */
            if (CommonConstant.ONE_COMMON_CONSTANT.equals(mcCouponInfo.getPurchaseFlag())) {
                /* 营销活动卡券为购买型 */
                rglog.error("营销活动编号 MC_NO=<{}> ，<{}>", mcNo, RespCodeEnum.WRONG_MC_PURCHASE_FLAG_ERROR.getRespDesc());
                return null;
            }

            /* 检查当前系统日期是否在对应卡券营销活动的有效期内 */
            int returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcCouponInfo.getMcStartDate(), mcCouponInfo.getMcEndDate());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("领取卡券日期<{}>并未在卡券营销活动<{}>的有效期<{}>~<{}>内,不可领取!", globalTxnDate,
                        mcNo, mcCouponInfo.getMcStartDate(), mcCouponInfo.getMcEndDate());
                return null;
            }

            /* 查询卡券信息表中剩余可领取卡券信息 */
            TMCouponInfo couponInfo = new TMCouponInfo();
            couponInfo.setInstId(globalInstId);
            couponInfo.setMcNo(mcNo);
            couponInfo.setRuleIndex(ruleIndex);

            /* 查询未生效或未领取的卡券状态的卡券 */
            TMCouponInfo tmCouponInfo = mompSelectClaimableFreeCoupon(couponInfo, claimCouponMcInfoBean.getCouponNo());
            if (null == tmCouponInfo) {
                rglog.error("法人机构<{}>的卡券营销活动<{}>的规则<{}>没有剩余可领取卡券!", globalInstId, mcNo, ruleIndex);
                return null;
            }

            /* 更新卡券状态 */
            couponInfo.setCouponNo(tmCouponInfo.getCouponNo());
            couponInfo.setClaimUserId(claimUser);
            couponInfo.setClaimDate(globalTxnDate);
            couponInfo.setClaimTime(globalTxnTime);
            couponInfo.setClaimType(claimUserType);
            couponInfo.setUpdateTime(globalTimeStamp);

            /* 根据卡券生效时间更新卡券状态 */
            if (CommonConstant.COUPON_IMMEDIATE_AVAILABLE.equals(mcCouponInfo.getAvailableDate())) {
                /* 卡券实时生效,需要将卡券状态更新为未核销 */
                couponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
                tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
            } else {
                /* 卡券第二天生效,需要将卡券状态更新为未生效 */
                couponInfo.setCouponStatus(CouponStatusEnum.NOT_ENABLED.getCouponStatusCode());
                tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_ENABLED.getCouponStatusCode());
            }

            /* 根据卡券有效期生成卡券有效期起止日期 */
            if (CommonConstant.COUPON_RELATIVE_DATE.equals(mcCouponInfo.getCouponDateFlag())) {
                /* 计算卡券有效起止日期并更新 */
//                    calculateCouponAvailableDate(couponInfo, mcCouponInfo.getCouponPeriod());
                calculateCouponAvailableDateImmediate(couponInfo, mcCouponInfo.getCouponPeriod());
                tmCouponInfo.setCouponStartDate(couponInfo.getCouponStartDate());
                tmCouponInfo.setCouponEndDate(couponInfo.getCouponEndDate());
            } else {
                /* 不需要更新卡券有效期止日期,有效起止日期仍为查询出来的日期更新卡券状态 */
                couponInfo.setCouponStartDate(tmCouponInfo.getCouponStartDate());
                couponInfo.setCouponEndDate(tmCouponInfo.getCouponEndDate());
            }

            /* 更新卡券状态 */
            returnCode = updateCouponInfoAndDate(couponInfo);

            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("更新卡券状态失败! RETURN_CODE=<{}>", returnCode);
                return null;
            }

            /* 转换卡券信息 */
            tmCouponInfo.setCouponStatus(couponInfo.getCouponStatus());
            tmCouponInfo.setClaimUserId(claimUser);
            tmCouponInfo.setClaimDate(globalTxnDate);
            tmCouponInfo.setClaimTime(globalTxnTime);
            tmCouponInfo.setClaimType(claimUserType);
            return convertCouponInfo(tmCouponInfo);

        } else {
            /* 获取卡券营销活动信息失败 */
            rglog.error("机构号 INST_ID=<{}>, 营销活动编号 MC_NO=<{}>，<{}>", globalInstId, mcNo, RespCodeEnum.GET_COUPON_MC_DETAIL_ERROR.getRespDesc());
            return null;
        }
    }

    /**
     * 查询卡券营销活动基本信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcCouponInfo 卡券类营销活动信息表
     * @author Jinan Liu
     * @date 2020/4/7 14:34
     */
    private TMMcCouponInfo selectCouponMcInfoByPrimaryKey(String instId, String mcNo) throws Exception {

        /* 营销活动信息正式表查询 */
        TMMcCouponInfo mcCouponInfo = new TMMcCouponInfo();
        mcCouponInfo.setInstId(instId);
        mcCouponInfo.setMcNo(mcNo);

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectCouponMcInfoByPrimaryKey(mcCouponInfo);
    }

    /**
     * 查询可领取的卡券信息
     *
     * @param tmCouponInfo 卡券信息表
     * @return cc.rengu.igas.momp.common.entity.TMCouponInfo 卡券信息表
     * @author Jinan Liu
     * @date 2020/4/7 14:54
     */
    private TMCouponInfo selectClaimableCouponbyRuleIndex(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.selectClaimableCouponbyRuleIndex(tmCouponInfo);
    }

    /**
     * 查询已锁定卡券信息
     *
     * @param tmCouponInfo 卡券信息表
     * @return cc.rengu.igas.momp.common.entity.TMCouponInfo 卡券信息表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/6/1 20:05
     */
    private TMCouponInfo selectLockedCouponByPrimaryKey(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.selectLockedCouponByPrimaryKey(tmCouponInfo);
    }

    /**
     * 更新卡券状态
     *
     * @param tmCouponInfo 卡券信息表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/6/1 18:36
     */
    private int updateCouponStatusByPrimaryKey(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.updateCouponStatusByPrimaryKey(tmCouponInfo);
    }

    /**
     * 更新已锁定卡券相关信息
     *
     * @param tmCouponInfo 卡券信息
     * @return int
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/4/7 14:55
     */
    private int updateLockedCouponInfo(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.updateLockedCouponInfo(tmCouponInfo);
    }

    /**
     * 更新已锁定卡券相关信息和卡券有效期
     *
     * @param tmCouponInfo 卡券信息
     * @return int
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/4/7 14:55
     */
    private int updateLockedCouponInfoAndDate(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.updateLockedCouponInfoAndDate(tmCouponInfo);
    }

    /**
     * 数据库实体类和接口实体类数据转换
     *
     * @param couponInfo 卡券信息
     * @return cc.rengu.igas.momp.facade.bean.CouponListInfoBean
     * @author Jinan Liu
     * @date 2020/4/7 15:04
     */
    private CouponListInfoBean convertCouponInfo(TMCouponInfo couponInfo) {
        CouponListInfoBean couponListInfoBean = new CouponListInfoBean();
        try {

            /* 卡券编号 */
            couponListInfoBean.setCouponNo(couponInfo.getCouponNo());
            /* 卡券有效起始日期 */
            couponListInfoBean.setCouponStartDate(couponInfo.getCouponStartDate());
            /* 卡券有效结束日期 */
            couponListInfoBean.setCouponEndDate(couponInfo.getCouponEndDate());
            /* 领取日期 */
            couponListInfoBean.setClaimDate(couponInfo.getClaimDate());
            /* 领取时间 */
            couponListInfoBean.setClaimTime(couponInfo.getClaimTime());
            /* 卡券状态 */
            couponListInfoBean.setCouponStatus(couponInfo.getCouponStatus());
            /* 卡券可抵扣金额 */
            couponListInfoBean.setCouponAmt(couponInfo.getCouponAmt());
            /* 领取人 */
            couponListInfoBean.setClaimUser(couponInfo.getClaimUserId());

        } catch (Exception e) {
            rglog.error("转换营销活动信息异常,异常信息:<{}>", StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        return couponListInfoBean;
    }

    /**
     * 计算卡券有效期
     *
     * @param tmCouponInfo 卡券信息表
     * @author Jinan Liu
     * @date 2020/6/1 20:35
     */
    private void calculateCouponAvailableDate(TMCouponInfo tmCouponInfo, String couponPeriod) {

        String startDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.ONE);
        String endDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.ONE + Integer.parseInt(couponPeriod));

        tmCouponInfo.setCouponStartDate(startDate);
        tmCouponInfo.setCouponEndDate(endDate);
    }

    /**
     * 计算卡券有效期
     *
     * @param tmCouponInfo 卡券信息表
     * @author liujinan
     * @date 2020/8/17 17:35
     */
    private void calculateCouponAvailableDateImmediate(TMCouponInfo tmCouponInfo, String couponPeriod) {

        String startDate = globalTxnDate;
        if (couponPeriod.equals(CommonConstant.ONE_COMMON_CONSTANT)) {
            String endDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, Integer.parseInt(couponPeriod));

            tmCouponInfo.setCouponStartDate(endDate);
            tmCouponInfo.setCouponEndDate(endDate);
        } else {
            String endDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, Integer.parseInt(couponPeriod) - 1);

            tmCouponInfo.setCouponStartDate(startDate);
            tmCouponInfo.setCouponEndDate(endDate);
        }
    }

    /**
     * 领取免费型卡券更新卡券相关信息和卡券有效期
     *
     * @param tmCouponInfo 卡券信息
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/11 19:55
     */
    private int updateCouponInfoAndDate(TMCouponInfo tmCouponInfo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.updateCouponInfoAndDate(tmCouponInfo);
    }

    /**
     * 查询可领取的免费卡券信息
     *
     * @param tmCouponInfo 卡券信息表
     * @return cc.rengu.igas.momp.common.entity.TMCouponInfo 卡券信息表
     * @author liujinan
     * @date 2020/8/12 14:54
     */
    private TMCouponInfo mompSelectClaimableFreeCoupon(TMCouponInfo tmCouponInfo, String couponNo) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        return couponInfoMapper.mompSelectClaimableFreeCoupon(tmCouponInfo, couponNo);
    }

    /**
     * 检查 上送 活动信息 金额字段不能为负数
     *
     * @param claimCouponMcInfoBean
     * @author ls
     * @date 2020/10/21
     */
    private void checkMcInfoFieldHasNegativeNumber(ClaimCouponMcInfoBean claimCouponMcInfoBean) {
        // 检查上传字段 不能为负数

        /*卡券领取数量	claimQuantity*/
        if (!StringUtil.isNullorEmpty(claimCouponMcInfoBean.getClaimQuantity()) && new BigDecimal(claimCouponMcInfoBean.getClaimQuantity()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 购买金额	purchaseAmt*/
        if (!StringUtil.isNullorEmpty(claimCouponMcInfoBean.getPurchaseAmt()) && new BigDecimal(claimCouponMcInfoBean.getPurchaseAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
    }

    /**
     * 查询营销活动用户信息表信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @param userId 用户ID
     * @return int
     * @throws Exception 异常信息
     * @author JL PANG
     * @since 2020/10/27 15:52
     */
    private List<TMMcUserInfo> checkUserInfo(String instId, String mcNo, String userId) throws Exception {

        McUserInfoMapper mcUserInfoMapper = new McUserInfoMapperImpl();
        return mcUserInfoMapper.selectMcUserInfoListByInstIdMcNoAcctNo(instId, mcNo, userId);
    }

    /**
     * 判断上送userId是否为json字符串
     *
     * @param userId
     * @return
     * @author pangjl
     * @date 2021.04.21
     */
    public boolean isJson(String userId) {
        try {
            JSONObject jsonObject = JSON.parseObject(userId);
            phoneNo = jsonObject.getString("phoneNo");
            cardNo = jsonObject.getString("cardNo");
            wechatId = jsonObject.getString("wechatId");
            alipayId = jsonObject.getString("alipayId");
            coreComId = jsonObject.getString("coreComId");
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * userIdFlag赋值
     *
     * @param userId
     * @author pangjl
     * @date 2021.05.06
     */
    private void checkUserId(String userId) {
        boolean isJson = isJson(userId);
        if (isJson) {
            userIdFlag = CommonConstant.THREE_COMMON_CONSTANT;
        } else {
            userIdFlag = CommonConstant.TWO_COMMON_CONSTANT;
        }

    }

    /**
     * 判断卡bin是否设置日周月季年限制且是否超限
     *
     * @param tmMcUserInfo 卡bin配置信息
     * @param userId       领取userId
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    public boolean limitOfJudgingTimes(TMMcUserInfo tmMcUserInfo, String userId) throws Exception {
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getRestriction())) {
            rglog.info("活动<{}>设置了活动期间卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getRestriction());
            int usedTimes = CommonConstant.ZERO;
            TMCouponInfo tmCouponInfo = getTmCouponInfoForMc(tmMcUserInfo.getMcNo(), userId);
            if (null != tmCouponInfo) {
                usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
            }
            rglog.info("用户活动期间领取卡券次数<{}>,活动期间领取限制<{}>", usedTimes, tmMcUserInfo.getRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getRestriction())) {
                rglog.info("用户活动期间领取卡券次数<{}>大于等于活动期间领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过活动限制领取次数" + tmMcUserInfo.getRestriction() + "次");

            }

        }
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getDayRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getDayRestriction())) {
            rglog.info("活动<{}>设置了单日卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getDayRestriction());
            int usedTimes = obtainDayJudgingTimes(tmMcUserInfo.getMcNo(), userId);
            rglog.info("用户单日领取卡券次数<{}>,单日领取限制<{}>", usedTimes, tmMcUserInfo.getDayRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getDayRestriction())) {
                rglog.info("用户单日领取卡券次数<{}>大于等于单日领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getDayRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过单日限制次数" + tmMcUserInfo.getDayRestriction() + "次");
            }
        } else {
            rglog.info("活动<{}>未设置了单日卡券领取次数限制,无需判断是否超限", tmMcUserInfo.getMcNo());
        }
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getWeekRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getWeekRestriction())) {
            rglog.info("活动<{}>设置了单周卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getWeekRestriction());
            int usedTimes = obtainWeekJudgingTimes(tmMcUserInfo.getMcNo(), userId);
            rglog.info("用户单周领取卡券次数<{}>,单周领取限制<{}>", usedTimes, tmMcUserInfo.getWeekRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getWeekRestriction())) {
                rglog.info("用户单周领取卡券次数<{}>大于等于单周领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getWeekRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过单周限制次数" + tmMcUserInfo.getWeekRestriction() + "次");
            }
        } else {
            rglog.info("活动<{}>未设置了单周卡券领取次数限制,无需判断是否超限", tmMcUserInfo.getMcNo());
        }
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getMonthRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getMonthRestriction())) {
            rglog.info("活动<{}>设置了单月卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getMonthRestriction());
            int usedTimes = obtainMonthJudgingTimes(tmMcUserInfo.getMcNo(), userId);
            rglog.info("用户单月领取卡券次数<{}>,单月领取限制<{}>", usedTimes, tmMcUserInfo.getMonthRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getMonthRestriction())) {
                rglog.info("用户单月领取卡券次数<{}>大于等于单月领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getMonthRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过单月限制次数" + tmMcUserInfo.getMonthRestriction() + "次");
            }
        } else {
            rglog.info("活动<{}>未设置了单月卡券领取次数限制,无需判断是否超限", tmMcUserInfo.getMcNo());
        }
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getQuerterRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getQuerterRestriction())) {
            rglog.info("活动<{}>设置了单季度卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getQuerterRestriction());
            int usedTimes = obtainQuerterJudgingTimes(tmMcUserInfo.getMcNo(), userId);
            rglog.info("用户单季度领取卡券次数<{}>,单季度领取限制<{}>", usedTimes, tmMcUserInfo.getQuerterRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getQuerterRestriction())) {
                rglog.info("用户单季度领取卡券次数<{}>大于等于单季度领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getQuerterRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过单季度限制次数" + tmMcUserInfo.getQuerterRestriction() + "次");
            }
        } else {
            rglog.info("活动<{}>未设置了单季度卡券领取次数限制,无需判断是否超限", tmMcUserInfo.getMcNo());
        }
        if (!StringUtil.isNullorEmpty(tmMcUserInfo.getYearRestriction()) && !CommonConstant.ZERO_COMMON_CONSTANT.equals(tmMcUserInfo.getYearRestriction())) {
            rglog.info("活动<{}>设置了单年卡券领取次数限制<{}>,判断是否超限", tmMcUserInfo.getMcNo(), tmMcUserInfo.getYearRestriction());
            int usedTimes = obtainYearJudgingTimes(tmMcUserInfo.getMcNo(), userId);
            rglog.info("用户单年领取卡券次数<{}>,单季年领取限制<{}>", usedTimes, tmMcUserInfo.getYearRestriction());
            if (usedTimes >= Integer.parseInt(tmMcUserInfo.getYearRestriction())) {
                rglog.info("用户单年度领取卡券次数<{}>大于等于单年度领取限制<{}>，不予优惠", usedTimes, tmMcUserInfo.getYearRestriction());
                throw new BizException(RespCodeEnum.CARD_VOUCHER_COLLECTION_LIMIT.getRespCode(), "卡券领取次数已超过单年限制次数" + tmMcUserInfo.getYearRestriction() + "次");
            }
        } else {
            rglog.info("活动<{}>未设置了单年卡券领取次数限制,无需判断是否超限", tmMcUserInfo.getMcNo());
        }
        return true;
    }

    /**
     * 获取用户单日卡券领取次数
     *
     * @param mcNo   活动号
     * @param userId 用户Id
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private int obtainDayJudgingTimes(String mcNo, String userId) throws Exception {
        int usedTimes = CommonConstant.ZERO;
        TMCouponInfo tmCouponInfo = getTmCouponInfo(mcNo, userId, globalTxnDate, globalTxnDate);
        if (null != tmCouponInfo) {
            usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
        }

        return usedTimes;
    }

    /**
     * 获取用户单周卡券领取次数
     *
     * @param mcNo   活动号
     * @param userId 用户Id
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private int obtainWeekJudgingTimes(String mcNo, String userId) throws Exception {
        int usedTimes = CommonConstant.ZERO;
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        //交易日期所属周周一的日期
        LocalDate beginDayOfWeek = inputDate.with(DayOfWeek.MONDAY);
        String firstDayOfWeek = beginDayOfWeek.toString().replaceAll("-", "");
        TMCouponInfo tmCouponInfo = getTmCouponInfo(mcNo, userId, firstDayOfWeek, globalTxnDate);
        if (null != tmCouponInfo) {
            usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
        }

        return usedTimes;
    }

    /**
     * 获取用户单月卡券领取次数
     *
     * @param mcNo   活动号
     * @param userId 用户Id
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private int obtainMonthJudgingTimes(String mcNo, String userId) throws Exception {
        int usedTimes = CommonConstant.ZERO;
        //交易日期所属月第一天的日期
        String firstDayOfMonth = MompDateUtil.getCurrentMonthFirstDay();
        TMCouponInfo tmCouponInfo = getTmCouponInfo(mcNo, userId, firstDayOfMonth, globalTxnDate);
        if (null != tmCouponInfo) {
            usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
        }

        return usedTimes;
    }

    /**
     * 获取用户单季度卡券领取次数
     *
     * @param mcNo   活动号
     * @param userId 用户Id
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private int obtainQuerterJudgingTimes(String mcNo, String userId) throws Exception {
        int usedTimes = CommonConstant.ZERO;
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        Month months = inputDate.getMonth();
        Month firstMonthOfQuarter = months.firstMonthOfQuarter();
        LocalDate quarterFirstDay = LocalDate.of(inputDate.getYear(), firstMonthOfQuarter, 1);
        //交易日期所属季度第一天的日期
        String firstDayOfQuarter = quarterFirstDay.toString().replaceAll("-", "");
        TMCouponInfo tmCouponInfo = getTmCouponInfo(mcNo, userId, firstDayOfQuarter, globalTxnDate);
        if (null != tmCouponInfo) {
            usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
        }

        return usedTimes;
    }

    /**
     * 获取用户单年卡券领取次数
     *
     * @param mcNo   活动号
     * @param userId 用户Id
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private int obtainYearJudgingTimes(String mcNo, String userId) throws Exception {
        int usedTimes = CommonConstant.ZERO;
        LocalDate inputDate = LocalDate.parse(globalTxnDate, DateTimeFormatter.BASIC_ISO_DATE);
        LocalDate yearFirstDay = LocalDate.of(inputDate.getYear(), Month.JANUARY, 1);
        String firstDayOfYear = yearFirstDay.toString().replaceAll("-", "");
        //交易日期所属季度第一天的日期
        TMCouponInfo tmCouponInfo = getTmCouponInfo(mcNo, userId, firstDayOfYear, globalTxnDate);
        if (null != tmCouponInfo) {
            usedTimes = Integer.parseInt(tmCouponInfo.getRemark4());
        }

        return usedTimes;
    }

    /**
     * 查询用户在某一周期内已领取券信息 数量
     *
     * @param mcNo
     * @param userId
     * @param periodStartDate
     * @param periodEndDate
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private TMCouponInfo getTmCouponInfo(String mcNo, String userId, String periodStartDate, String periodEndDate) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        TMCouponInfo tmCouponInfo = couponInfoMapper.selectUserCouponCountByInstIdAndMcNoAndDate(globalInstId, mcNo, userId, periodStartDate, periodEndDate);
        return tmCouponInfo;
    }

    /**
     * 查询用户活动期间内已领取券信息 数量
     *
     * @param mcNo
     * @param userId
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/8/23 15:52
     */
    private TMCouponInfo getTmCouponInfoForMc(String mcNo, String userId) throws Exception {

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        TMCouponInfo tmCouponInfo = couponInfoMapper.selectUserCouponCountByMarketingPlatform(mcNo, userId);
        return tmCouponInfo;
    }

    /**
     * 根据上送的json字符串 用逗号拼接
     *
     * @return
     * @author liujinan
     * @date 20201.9.1
     */
    private String getUserList() {
        String userIdList = "";
        if (!StringUtil.isNullorEmpty(phoneNo)) {
            userIdList = userIdList + phoneNo + ",";
        }
        if (!StringUtil.isNullorEmpty(cardNo)) {
            userIdList = userIdList + cardNo + ",";
        }
        if (!StringUtil.isNullorEmpty(wechatId)) {
            userIdList = userIdList + wechatId + ",";
        }
        if (!StringUtil.isNullorEmpty(alipayId)) {
            userIdList = userIdList + alipayId + ",";
        }
        if (!StringUtil.isNullorEmpty(coreComId)) {
            userIdList = userIdList + coreComId + ",";
        }
        return userIdList;
    }
}
